package com.rupertjones.globalcron.domain;

import com.rupertjones.globalcron.domain.audit.Auditable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import static java.lang.String.format;

/**
 * <p>&copy Rupert Jones 2011,2012</p>
 *
 * @author rup
 */
@Entity
@Table(name = "user")
public class User extends BaseEntity implements Auditable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column
    private String username;

    @Column
    private String password;

    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.ALL })
    @JoinTable(
            name = "user_role",
            joinColumns = @JoinColumn(name = "user"),
            inverseJoinColumns = @JoinColumn(name = "role")
    )
    private Set<Role> roles = new HashSet<Role>();

    @Column(name = "full_name")
    private String fullName;

    @Column(name = "last_login")
    private Date lastLogin;

    @Override
    public void setId(int id) {
        this.id = id;
    }

    @Override
    public int getId() {
        return this.id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    public void addRole(Role role) {
        this.roles.add(role);
    }

    public Date getLastLogin() {
        return lastLogin;
    }

    public void setLastLogin(Date lastLogin) {
        this.lastLogin = lastLogin;
    }

    public void registerLogin() {
        lastLogin = new Date();
    }

    public boolean hasRole(Role role) {
        return roles.contains(role);
    }

    public void clearRoles() {
        roles.clear();
    }

    public String toString() {
        return username;
    }

    @Override
    public String toAuditLog() {
        StringBuilder rolesReport = new StringBuilder();
        for (Role role : roles) {
            rolesReport.append(role.getName()).append(" ");
        }
        return format("[id: %s] [username: %s] [full name: %s] [last login: %s] [roles: %s]", id, username, fullName, lastLogin, rolesReport.toString().trim());
    }


    @Override
    public AuditLogType getAuditTypeForUpdate() {
        return AuditLogType.EDIT_USER;
    }

    @Override
    public AuditLogType getAuditTypeForInsert() {
        return AuditLogType.ADD_USER;
    }
}
